Published 2007-05-16 16:38:00

I thought I'd go some of my random thoughts of working with extjs, as creating quite large applicaitons with extjs is quite new, and as the projects I've used it on have been refactored a few times, I'm beginning to develop approaches that make code more maintainable, and faster to develop.

This is quite a big post - so the contents in the Extended body....

Defining objects

Since Javascript doesnt have namespaces, or the class keyword, there are a number of ways objects can be defined. Often an object in js is just a way to reduce the polution of the namespace with global functions.

The simplest way to define a class is for static use

aaa = {
ccc: "test",
bbb : function() { alert(this.cc); }
}

aaa.bbb();

I'm comming to the conclusion that this is the best way to deal with code that will only have one instance, eg the main layout, or a widget.

You cannot instantate this as an object (no "new" needed), extending it is possible, (although I've not tested this idea yet), Most of the User Interface creation and reaction code is now being written this way.

It has a number of advantages over the next method, for developing, as accessing the variables for debugging is feasible.

This is really a evolution for my old code as well, as previously I tended to use function name prefixes, and binding that into the object.


Class definitions with private variables
aaa = (function () {
var myprivate;
return {
setIt: function(val) { myprivate = val; }
getIt: function() { return myprivate; }
}
})();

This method is common in extjs for libraries where Jack does not want users changing or reading the private variables. It however leaves you with the problem that inspecting those variable for debuging is difficult. It has a slight benefit that you can avoid putting "this." to access your private variables.

Extending objects with Ext.extend
function MyCombo (config) {
// set up your datasource here..
MyCombo.superclass.constructor.call(this,config);
}
Ext.extend(MyCombo, Ext.form.ComboBox, {
displayField:'title',
typeAhead: true,
loadingText: 'Searching...',
forceSelection: true,
allowBlank: false,
width: 160,
minChars: 1,
pageSize:10,
hideTrigger:true,
displayField: 'FullName',
valueField: 'id'
}


This resembles the more classic object definition pattern, and is the core behind extjs. It's handy for writing common reusable components, and extending extjs objects to create your application specific widgets.



Fixing bugs and miss-behaviour in extjs

Every so often when using extjs, you come across issues with the libraries that result in widgets not behaving how you want them to (or expect them to.).

To fix this you have a few options
  • redeclare the whole class.
  • extend the class overriding the methods or properties that you need fixed.
  • overide one or more of the objects prototypes
    eg. Fix to use the input maxWidth field - so that overtyping results in chopped data.
Ext.form.TextField.prototype.initValue = function()
{
if(this.value !== undefined){
this.setValue(this.value);
}else if(this.el.dom.value.length > 0){
this.setValue(this.el.dom.value);
}
if (!isNaN(this.maxLength) &&
(this.maxLength *1) > 0 &&
(this.maxLength != Number.MAX_VALUE)) {
this.el.dom.maxLength = this.maxLength *1;
}
};



write - test - fix cycle

I normally use write on commit with an svn mounted drive, so after saving the file in my editor, I can reload the page from a remote server in firefox. The only snag with this approach is that I'm often only editing a small part of the application, and reloading the whole lot is both timeconsuming (well a second or two!) and a little network intensive..

As I have been breaking the classes that deal with specific area's of the code into seperate .js files, I really only need to reload that js file. So after a bit of googling and hacking I came up with this simple funciton. -

 include =  function(url){
var con = new Ext.data.Connection();
con.request({
url: url + '?ts=' + (new Date().format('Ymd_his')),
method: 'GET',
callback: function(opts, success, response) {

if (!success) {
Ext.MessageBox.alert("Error",
success ? response.responseText :
"Error saving data - try again");
return;
}
var o = document.getElementById('script_' + url)
if (o) {
o.parentNode.removeChild(o);
}

s = document.createElement('script');
s.setAttribute('id', 'script_' + url);
s.setAttribute('type', 'text/javascript');
s.appendChild(document.createTextNode(response.responseText));
document.getElementsByTagName("head")[0].appendChild(s);
}
});

}

I tried various other methods, like adding <script> tags with src in DOM, but the browser refused to refresh the code.. - so this method of dumping the source inside of a script tag seems to work best for testing.

It works pretty much like good ole PHP's include method. eg.
include("MyProject/templates/images/js/mylib.js");

Which can be run at the command line in firebug. Refreshing the object definition, enabling me to test changes to dialogs and forms without having to reload the whole page.

I guess hoping that Ctrl-S in the editor could trigger that to happen automatically may be going a bit far...


HTML morphing or just javascript


When I started using extjs, I had tried out dojo, and quite liked the way it used HTML attributes to create dynamic components. I had got to the point of writing simple Helper Class to convert tables and forms into grids and forms with Ext.form elements, and although it worked. I later attempted to just define my dialog, form and grids directly only using javascript and extjs.

Having tried this alternative, it's pretty clear that the original idea of using HTML attributes doesnt really have much advantage, and espicially combined with the include() method the idea of using pure javascript to define these components has proved far more efficient. In reality I dont think I will resort to HTML for much more than text content areas that need rendering. The whole layout, dialogs, forms etc will now be purely done in Javascript.


Moving to Extjs's XMLHttpRequest call.


As usual when you start using a library, You never get time to learn the whole thing, so I had initially been relying on my old XMLHttpRequest wrapper to send data to the server, but as I began to dig deeper into extjs, I was able to start removing my old Wrapper code and use the code in extjs. Which Is better tested (as my library was originally morphed from some code that worked with the XUL app's I was writing). And also alot more powerfull.

The save code for my dialogs looks a bit like this..



dialog.el.mask("Saving...");
var con = new Ext.data.Connection();
con.request({
url: baseURL + "/mypage.txt", // where to post to..
params: params, // << key value object with data to send
method: 'POST',
callback: function(opts, success, response) {
dialog.el.unmask(true); // unmask the dialog.
if (!success || ("OK" != response.responseText)) {
Ext.MessageBox.alert("Error", success ?
response.responseText :
"Error saving data - try again");
return;
}
dialog.hide();
// code to update stuff that's affected by the saved form working..
// goes here...

}

});

Submitting forms.

Having moved to using Ext.form.Form, one snag I did find was that the default method for getting form values was
   var ar = form.getValues();

unfortunatly, this urlencodes both the key and value of the data, so using that with the code above to send the data makes a complete mess..

This little trick helps solve that..

Ext.form.Form.prototype.getValuesRaw = function() {
var ar = this.getValues();
var ret = {};
for(var i in ar) {
ret[decodeURIComponent(i)] = decodeURIComponent(ar[i]);
}
return ret;
};


Comboboxes - load once, not all the time.

The combo box on ExtJs, can autocompelete using JSON calls to the server, With lists that dont change often, I considered this a bit of an overkill, so by calling the load method in the extended class, and setting the mode to 'local', I was able to deliver a more efficient combo.

function myCombo() {
this.Store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: baseURL + '/MyLister.js'
}),
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'totalCount',
id: 'id'
}, [ 'id', 'fullname' ])
});

}
this.Store.load();
config.store = this.Store;
myCombo.superclass.constructor.call(this, config);
}

Ext.extend(FlexyCash.AccountCombo, Ext.form.ComboBox, {
mode: 'local',
.....
});

Then if you need to refresh the list at any time (eg. before the dialog appears), just call the combo.store.load() method..

IE Gotcha's


Normally when I do any web development, It seems like 20% at the end of the project is spent working around IE bugs, so even with my extjs projects I've been developing in firefox and testing later with IE. However the only serious issue that I've found that catches me out has been that IE doesnt like trailing comma's in object definitions.

var a = {
a: "b",
c: "d", //<< oops trailing comma!
};

Otherwise It's pretty easy going developing cross platform applications with extjs..




Mentioned By:
www.dzone.com : Developing with Extjs - tricks and tips. (6206 referals)
google.com : extjs (519 referals)
google.com : Ext.data.Connection (313 referals)
google.com : extjs XMLHttpRequest (206 referals)
www.phpeye.com : Developing with Extjs - tricks and tips. - Alan Knowles|PHP教程|PHP实例|PHP新闻|PHP5|PEAR|PHP框架|PHPEye - Powered by Ha (176 referals)
www.stumbleupon.com : StumbleUpon &#187; Your page is now on StumbleUpon! (169 referals)
google.com : extjs combobox (164 referals)
www.blinklist.com : Discover the best extjs and extjs sites (158 referals)
swik.net : AKBK home - Smoking toooooo much PHP - Developing with Extjs - tricks and tips. - SWiK (138 referals)
www.gennio.com : extjs en Gennio (131 referals)
google.com : extjs json (121 referals)
www.megite.com : Discover From Your Favorite Topic or Web Page: extjs (119 referals)
google.com : extjs forms (109 referals)
google.com : april (103 referals)
www.phpchina.com : Developing with Extjs - tricks and tips. - Dennis's Blog - PHPChina ԴŻ - Powered by X-Space (94 referals)
google.com : Ext.form.combobox (74 referals)
www.megite.com : Discover From Your Favorite Topic or Web Page: extjs json (73 referals)
www.planet-php.net : Planet PHP (72 referals)
google.com : extjs alternative (69 referals)
google.com : december (68 referals)

Comments

Thanks
Very nice run-down Alan. Thanks...
#0 - Matthew Delmarter ( Link) on 2007-05-16 18:39:13 Delete Comment
Architect
Lilya : First Jsf ExtJs Widgets is available for download http://qlogic.ma/lilya

I need your comments.
#1 - Loukili ( Link) on 2007-07-29 01:27:46 Delete Comment
Thank you for your tips
Nice tips, thanks.

I agree with "Moving to Extjs's XMLHttpRequest call".

Aamof, we have that same situation, where we've been having this little home bakery for some time, but now we are at the stage where we can start making the transition, beginning with small parts of our app, and moving to Ext.Stores, ViewPort, TabPanels, FormPanels and so on.

I think a lot of dev teams have had that same dilemma: wanted to hop on the AJAX toolbox train in a big way, but didn't have time to really look into everything that's available (JQuery, Dojo, Mootools, DhtmlX, ExtJS and so on). Those kits tend to be a lot more to chew than you can swallow in one day whatnot, and all of them have a certain mindset that comes with the package. There is definitely, absolutely NO shortcut to learning any of those toolkits properly within hours, period.

Personally, having project experience from DhtmlX and ExtJS I can say that it's easy to get lost in the grandeur of details of a particular toolkit too early.

It's important to take time to specify what the application should be able to do, better yet even try to imagine what it should be able to do in the near future, instead of a "we'll figure it out as we go along" -type of approach. Whether you just want a nice calendar picker or progress bar, an out-of-the-box full-fledged killer library or something in between will affect your choice of toolkit.

ExtJS is in my opinion something in between: it has some nice components and more on the way, but it certainly wasn't built to exhaustively cover absolutely every need.

That said, it has a very consistent and logical means to create extensions, a vibrant user collective, extremely active forums, and a really great API with up-to-date documentation. The learning curve is not instant, nor is it steep. It's in the middle, more or less.

Those who are in a J2EE environment and are thinking about a taglib, be sure to check out http://www.exttld.com/. It's work in progress, but is very easy to extend.


#2 - Tapani Jalonen ( Link) on 2009-01-23 20:05:31 Delete Comment
Nice content, but another site is using the same content
Thanks this is a good way of explaining the ins and outs of extjs. Btw, I stumbled on a site having the exact same content as this one, you might wanna check it out?

check this url address:
phpchina (dot) com (slash) html (slash) 78 (slash) 78-10281 (dot) html
#3 - absynth ( Link) on 2009-12-17 16:35:43 Delete Comment
Ext.extend
var someglobal = new MyCombo();

or

var myapp.somecombo = new MyCombo();
#4 - Alan Knowles ( Link) on 2010-10-05 16:07:26 Delete Comment

Add Your Comment

Follow us on